﻿#include <QTimer>
#include <QDataStream>
#include <QFile>
#include <QCoreApplication>
#include <QFileInfo>
#include <QDateTime>
#include <QDir>

#include <inuorui/Log>

#include "saveprivate.h"
#include "isave.h"

static const QString sc_strBackupSuffix = ".bak";
static const int sc_nSaveInterval = 30 * 1000;

SavePrivate::SavePrivate(int version, const QString &name, bool autoLoad, bool autoSave, ISave *q) :
    QObject(),
    q_ptr(q),
    m_nVersion(version),
    m_strName(name),
    m_bAutosave(autoSave)
{
    if (m_strName.isEmpty() || m_nVersion ==  0)
    {
        return;
    }

    if (autoLoad)
    {
        QTimer::singleShot(0, this, &SavePrivate::load);
    }

    if (m_bAutosave)
    {
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, &SavePrivate::save);
        timer->start(sc_nSaveInterval);

        connect(qApp, &QCoreApplication::aboutToQuit, this, [this]()
        {
            save();
            setStopSave();
        });
        connect(qApp, &QCoreApplication::aboutToQuit, timer, &QTimer::stop);
    }
}

SavePrivate::~SavePrivate()
{
    if (m_bAutosave)
    {
        save();
        setStopSave();
        if (qApp != nullptr)
        {
            disconnect(qApp, 0, this, 0);
        }
    }
}

void SavePrivate::setStopSave()
{
    m_bStopSave = true;
}

QString SavePrivate::saveFileName() const
{
    return ISave::dataDir() + m_strName;
}

QString SavePrivate::backUpFileName() const
{
    return ISave::dataDir() + m_strName + sc_strBackupSuffix;
}

void SavePrivate::load()
{
    if (m_strName.isEmpty() || m_nVersion ==  0)
    {
        return;
    }

    int oldVersion = 0;
    QByteArray oldData;
    QString fileName;
    QFileInfo fiSave(saveFileName());
    QFileInfo fiBackup(backUpFileName());
    if (fiSave.exists() && fiBackup.exists() == false)
    {
        fileName = fiSave.absoluteFilePath();
    }
    else if (fiSave.exists() == false && fiBackup.exists())
    {
        fileName = fiBackup.absoluteFilePath();
    }
    else if (fiSave.exists() && fiBackup.exists())
    {
        if (fiSave.lastModified() <= fiBackup.lastModified())
        {
            fileName = fiSave.absoluteFilePath();
        }
        else
        {
            fileName = fiBackup.absoluteFilePath();
        }
    }

    QFile file(fileName);
    if (file.exists() && file.open(QFile::ReadOnly))
    {
        QDataStream ds(&file);
        ds.setVersion(ISave::dataStreamVersion());
        ds >> oldVersion >> oldData;
        file.close();
    }

    QString info = QStringLiteral("载入设置 %1，版本号 %2。");
    info = info.arg(fileName.isEmpty() ? m_strName : fileName).
           arg(oldVersion);
    loginfomessage(info);

    q_ptr->loadOldData(oldData, oldVersion);
}

void SavePrivate::save()
{
    if (qApp == nullptr ||
        m_bStopSave ||
        m_strName.isEmpty() ||
        m_nVersion ==  0)
    {
        return;
    }

    QByteArray data = q_ptr->saveCurrentData();

    QDir dir(ISave::dataDir());
    if (dir.exists() == false)
    {
        dir.mkpath(dir.absolutePath());
    }

    //保存设置
    QFile file(saveFileName());
    if (file.open(QFile::WriteOnly))
    {
        QDataStream ds(&file);
        ds.setVersion(ISave::dataStreamVersion());
        ds << m_nVersion << data;
        file.close();

        loginfomessage(QStringLiteral("保存设置 ") +
                       file.fileName() +
                       QStringLiteral("成功。"));
    }
    else
    {
        logerrormessage(QStringLiteral("保存设置 ") +
                        file.fileName() +
                        QStringLiteral("失败。"));
    }

    //保存备份设置
    QFile fileBackup(backUpFileName());
    if (fileBackup.open(QFile::WriteOnly))
    {
        QDataStream ds(&fileBackup);
        ds.setVersion(ISave::dataStreamVersion());
        ds << m_nVersion << data;
        fileBackup.close();

        loginfomessage(QStringLiteral("保存设置 ") +
                       fileBackup.fileName() +
                       QStringLiteral("成功。"));
    }
    else
    {
        logerrormessage(QStringLiteral("保存设置 ") +
                        fileBackup.fileName() +
                        QStringLiteral("失败。"));
    }
}
